package com.devops.admin.graphql;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.devops.admin.model.DOSModel;
import com.devops.admin.model.DOSProjectGroup;
import com.devops.admin.model.DOSProjectGroupPo;
import com.devops.admin.model.TableResult;
import com.devops.admin.po.DOSProjectAuthorizePo;
import com.devops.admin.po.DOSProjectGroupUserRelationPo;
import com.devops.admin.service.DOSProjectApplyAuthorizeService;
import com.devops.admin.service.DOSProjectGroupService;
import com.devops.admin.service.DOSProjectGroupUserRelationService;
import com.devops.admin.util.Assert;
import com.devops.admin.vo.DOSPageVo;
import com.devops.admin.vo.DOSProjectAuthorizeVo;
import com.devops.admin.vo.DOSProjectGroupUserRelationVo;
import com.devops.common.annotation.DOSLog;
import com.devops.constant.DevOpsConstant;
import com.netflix.graphql.dgs.DgsComponent;
import com.netflix.graphql.dgs.DgsMutation;
import com.netflix.graphql.dgs.DgsQuery;
import com.netflix.graphql.dgs.InputArgument;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName DOSProjectGroupDataFetcher
 * @Description TODO
 * @Author heyabo
 * @Date 2022/8/4 09:51
 * @Version 1.0
 **/
@DgsComponent
public class DOSProjectGroupDataFetcher {

    @Autowired
    private DOSProjectGroupService dosProjectGroupService;
    @Autowired
    private DOSProjectGroupUserRelationService dosProjectGroupUserRelationService;
    @Autowired
    private DOSProjectApplyAuthorizeService dosProjectApplyAuthorizeService;
    @Value("${project.similarity.limit}")
    private Double similarityLimit;

    /**
     * @Author heyabo
     * @Description 添加项目组
     * @Date 16:12 2022/3/21
     * @Param [projectGroup]
     * @return java.lang.Boolean
     **/
    @DgsMutation
    @DOSLog(description = "添加项目组")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public DOSProjectGroup saveProjectGroup(@InputArgument DOSProjectGroup projectGroup){
        Assert.isTrue(dosProjectGroupService.count(
                Wrappers.<DOSProjectGroup>lambdaQuery().eq(DOSProjectGroup::getGroupName,projectGroup.getGroupName()))
                        == 0,
                "项目组名称重复");
        if (projectGroup.getCheckType() == 0) {
            List<String> similarProjectGroupNames = dosProjectGroupService.getSimilarProjectGroupName(projectGroup.getGroupName(),similarityLimit);
            Assert.isSimilar(ObjectUtil.isEmpty(similarProjectGroupNames), projectGroup.getGroupName()+"与" + StringUtils.join(similarProjectGroupNames, ",") + "相似度较高，是否保存");
        }
        dosProjectGroupService.save(projectGroup);
        return projectGroup;
    }

    /**
     * @Author heyabo
     * @Description 更新项目组
     * @Date 16:13 2022/3/21
     * @Param [projectGroup]
     * @return java.lang.Boolean
     **/
    @DgsMutation
    @DOSLog(description = "更新项目组")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public Boolean updateProjectGroup(@InputArgument DOSProjectGroup projectGroup){
        Assert.isTrue(ObjectUtil.isNotNull(projectGroup.getId()),"项目组的id不能为空");
        if (StrUtil.isNotBlank(projectGroup.getGroupName())) {
            List<DOSProjectGroup> projectGroups = dosProjectGroupService.list();
            AtomicInteger count = new AtomicInteger(0);
            projectGroups.forEach(group -> {
                if (group.getId().intValue() != projectGroup.getId().intValue()
                        && group.getGroupName().equals(projectGroup.getGroupName())) {
                    count.set(1);
                }
            });
            Assert.isTrue(count.get() == 0, "项目组名称已存在");
        }
        DOSProjectGroup byId = dosProjectGroupService.getById(projectGroup.getId());
        if (!byId.getGroupName().equals(projectGroup.getGroupName()) && projectGroup.getCheckType() == 0){
            List<String> similarProjectGroupNames = dosProjectGroupService.getSimilarProjectGroupName(projectGroup.getGroupName(),similarityLimit);
            Assert.isSimilar(ObjectUtil.isEmpty(similarProjectGroupNames), projectGroup.getGroupName()+"与" + StringUtils.join(similarProjectGroupNames, ",") + "相似度较高，是否修改");
        }
        return dosProjectGroupService.updateById(projectGroup);
    }

    /**
     * @Author heyabo
     * @Description 根据id删除项目组
     * @Date 16:14 2022/3/21
     * @Param [projectGroupId]
     * @return java.lang.Boolean
     **/
    @DgsMutation
    @DOSLog(description = "根据id删除项目组")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public Boolean deleteProjectGroup(@InputArgument Integer projectGroupId){

        return dosProjectGroupService.deleteProjectGroup(projectGroupId);
    }

    /**
     * @Author heyabo
     * @Description //TODO
     * @Date 15:56 2022/9/5
     * @Param []
     * @return com.devops.common.utils.Message
     **/
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    @DgsMutation
    @DOSLog(description = "为项目组分配人员")
    public Boolean distributionProjectGroupUsers(@InputArgument DOSProjectGroupUserRelationVo relation){
        return dosProjectGroupUserRelationService.saveProjectGroupUserRelation(relation);
    }

    /**
     * @Author heyabo
     * @Description 分页查询项目组列表
     * @Date 16:28 2022/3/21
     * @Param [modelPage]
     * @return com.devops.admin.model.TableResult<com.devops.admin.model.DOSProjectGroup>
     **/
    @DgsQuery
    @DOSLog(description = "分页查询项目组列表")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public TableResult<DOSProjectGroup> getProjectGroupList(@InputArgument DOSModel modelPage, @InputArgument DOSPageVo pageVo){
        return dosProjectGroupService.getListPage(modelPage,pageVo);
    }

    /**
     * @Author heyabo
     * @Description 根据项目组名称模糊查询
     * @Date 16:44 2022/3/21
     * @Param [projectGroup]
     * @return com.devops.admin.model.TableResult<com.devops.admin.model.DOSProjectGroup>
     **/
    @DgsQuery
    @DOSLog(description = "根据项目组名称模糊查询")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public TableResult<DOSProjectGroup> getProjectGroupByName(@InputArgument DOSProjectGroup projectGroup,@InputArgument DOSPageVo pageVo){
        return dosProjectGroupService.getProjectGroupByName(projectGroup,pageVo);
    }

    /**
     * @Author heyabo
     * @Description 获取待授权项目列表
     * @Date 09:08 2022/3/22
     * @Param []
     * @return com.devops.admin.model.TableResult
     **/
    @DgsQuery
    @DOSLog(description = "获取待授权项目列表")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.SUPER_ADMINISTRATOR,DevOpsConstant.RoleCode.ADMINISTRATOR,
            DevOpsConstant.RoleCode.QA_ADMINISTRATOR},logical = Logical.OR)
    public TableResult<DOSProjectAuthorizePo> getProjectAuthorizeList(@InputArgument DOSProjectAuthorizeVo authorizeVo, @InputArgument DOSPageVo pageVo){
        return dosProjectApplyAuthorizeService.getAuthorizeList(authorizeVo,pageVo);
    }

    /**
     * @Author heyabo
     * @Description 查询所有项目组列表
     * @Date 16:28 2022/3/21
     * @Param [modelPage]
     * @return com.devops.admin.model.TableResult<com.devops.admin.model.DOSProjectGroup>
     **/
    @DgsQuery
    public List<DOSProjectGroup> getAllProjectGroupList(){
        return dosProjectGroupService.getListPage();
    }

    /**
     * @Author heyabo
     * @Description 根据人员的角色信息查询项目组与项目的级联信息
     * @Date 10:23 2022/7/22
     * @Param []
     * @return java.util.List<com.devops.admin.model.DOSProjectGroupPo>
     **/
    @DgsQuery
    @DOSLog(description = "根据人员的角色信息查询项目组与项目的级联信息")
    @RequiresPermissions(DevOpsConstant.RoleCode.LOGIN_USER)
    public List<DOSProjectGroupPo> getCascade() {
        return dosProjectGroupService.getCascade();
    }

    /**
     * @Author heyabo
     * @Description 查询项目组成员绑定关系
     * @Date 17:24 2022/9/5
     * @Param [projectGroupId]
     * @return java.util.List<com.devops.admin.po.DOSProjectGroupUserRelationPo>
     **/
    @DgsQuery
    @DOSLog(description = "查询项目组成员绑定关系")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.LOGIN_USER},logical = Logical.OR)
    public List<DOSProjectGroupUserRelationPo> getProjectGroupMember(@InputArgument Integer projectGroupId){

        return dosProjectGroupUserRelationService.getGroupMember(projectGroupId);
    }

    /**
     * @Author heyabo
     * @Description 查询项目组负责人绑定关系
     * @Date 09:32 2022/9/6
     * @Param [projectGroupId]
     * @return java.util.List<com.devops.admin.po.DOSProjectGroupUserRelationPo>
     **/
    @DgsQuery
    @DOSLog(description = "查询项目组负责人绑定关系")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.LOGIN_USER},logical = Logical.OR)
    public List<DOSProjectGroupUserRelationPo> getProjectGroupManager(@InputArgument Integer projectGroupId){

        return dosProjectGroupUserRelationService.getGroupManager(projectGroupId);
    }

    /**
     * 获取项目组所有人员
     * @param projectGroupId
     * @return
     */
    @DgsQuery
    @DOSLog(description = "获取项目组所有人员")
    @RequiresPermissions(value = {DevOpsConstant.RoleCode.LOGIN_USER},logical = Logical.OR)
    public List<DOSProjectGroupUserRelationPo> getProjectGroupUsers(@InputArgument Integer projectGroupId){

        return dosProjectGroupUserRelationService.getProjectGroupUsers(projectGroupId);
    }
}
